#include "RenumberTerminalsTask.h"

#include "LeGraphicsView/LeGraphicsItem.h"
#include "LeGraphicsView/LeGraphicsItemLayer.h"
#include "LeGraphicsView/LeGraphicsScene.h"
#include "LeGraphicsView/LeGraphicsView.h"

#include "qtpropertybrowser/qttreepropertybrowser.h"
#include "qtpropertybrowser/qtvariantproperty.h"

#include "LeIpc7351/LeIpc7351.h"
#include "GraphicsItems.h"

#include <QGraphicsSceneEvent>
#include <QMouseEvent>

RenumberTerminalsTask::RenumberTerminalsTask(QObject *parent)
    : AbstractTask(parent)
    , LeGraphicsSceneEventFilter()
    , m_propertyManager(new QtVariantPropertyManager(this))
    , m_propertyEditorFactory(new QtVariantEditorFactory(this))
{
}

RenumberTerminalsTask::~RenumberTerminalsTask()
{

}

void RenumberTerminalsTask::start()
{
    initialiseNumbering();
    attachPropertyManager();
    attachScene();
    emit started(this);
}

void RenumberTerminalsTask::accept()
{
    detachScene();
    detachPropertyManager();
    revertNumbering();
    emit accepted(this);
}

void RenumberTerminalsTask::reject()
{
    detachScene();
    detachPropertyManager();
    applyNumbering();
    emit rejected(this);
}

bool RenumberTerminalsTask::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
//    auto items = scene()->items(event->scenePos(), Qt::IntersectsItemShape, Qt::DescendingOrder, view()->transform());

//    QList<TerminalItem*> terms;
//    for (auto item: items)
//        if (item->type() == TerminalItem::Type)
//            terms.append(static_cast<TerminalItem*>(item));

//    if (terms.isEmpty())
//        return false;

//    auto term = terms.first();
//    if (m_candidates.isEmpty())
//    {
//        term->setStateFlag(LeGraphicsStyle::MarkedBad, false);
//        term->setStateFlag(LeGraphicsStyle::MarkedGood, true);
//        m_toRenumber.removeOne(term);
//        m_renumbered.append(term);
//        term->setLabel(QString::number(m_renumbered.count()));
//        m_hitPath.append(QLineF(event->scenePos(), event->scenePos()));
//    }
//    else // TODO: Move to mouseRelease()
//    {
//        for (auto term: m_candidates)
//        {
//            term->setStateFlag(LeGraphicsStyle::MarkedBad, false);
//            term->setStateFlag(LeGraphicsStyle::MarkedGood, true);
//            m_toRenumber.removeOne(term);
//            m_renumbered.append(term);
//        }
//        //m_hitPath.append(QLineF(event->scenePos(), event->scenePos()));
//        m_hitPath.clear();
//        m_candidates.clear();
//    }
    return true;
}

// TODO: 2 modes (eg. Ctrl pressed)
// 1 - use a line as a hit path (2 cliks, first and last)
// 2 - number one terminal at a time, (1 click = 1 number change)
bool RenumberTerminalsTask::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
//    if (m_hitPath.isEmpty())
//        return false;

//    // Get all items on the hit path
//    QLineF &line = m_hitPath.last();
//    QRectF oldHitRect(line.p1(), line.p2());
//    line.setP2(event->scenePos());
//    QRectF newHitRect(line.p1(), line.p2());
//    QPainterPath path;
//    path.moveTo(line.p1());
//    path.lineTo(line.p2());
//    auto items = scene()->items(path, Qt::IntersectsItemShape, Qt::DescendingOrder, view()->transform());

//    // Filter-out non terminal items
//    QList<TerminalItem*> terms;
//    for (auto item: items)
//        if (item->type() == TerminalItem::Type)
//            terms.append(static_cast<TerminalItem*>(item));

//    // Build up list of terminal items hit by path that need to be renumbered
//    m_candidates.clear();
//    for (auto term: m_toRenumber)
//    {
//        if (terms.contains(term))
//        {
//            term->setStateFlag(LeGraphicsStyle::MarkedBad, false);
//            term->setStateFlag(LeGraphicsStyle::MarkedGood, true);
//            m_candidates.append(term);
//        }
//    }
//    // Build up list of terminal items not hit by path that need to be renumbered
//    QList<TerminalItem*> remaining;
//    for (auto term: m_toRenumber)
//    {
//        if (!terms.contains(term))
//        {
//            term->setStateFlag(LeGraphicsStyle::MarkedBad, true);
//            term->setStateFlag(LeGraphicsStyle::MarkedGood, false);
//            remaining.append(term);
//        }
//    }

//    // Sort candidates by hit ordering along the hit path
//    std::sort(m_candidates.begin(), m_candidates.end(),
//              [line](TerminalItem *t1, TerminalItem *t2) {
//        return QLineF(line.p1(), t1->scenePos()).length()
//                < QLineF(line.p1(), t2->scenePos()).length();
//    });

//    // Renumber them accordingly
//    int n = m_renumbered.count();
//    for (auto term: m_candidates)
//        term->setLabel(QString::number(++n));
//    for (auto term: remaining)
//        term->setLabel(QString::number(++n));

//    // FIXME: Only invalidate the foreground scene layer
//    // FIXME: Only invalidate rects that need to be redrawn
//    scene()->update(oldHitRect.normalized());
//    scene()->update(newHitRect.normalized());
//    scene()->update(QRectF());
    return true;
}

bool RenumberTerminalsTask::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event)
    return true;
}

bool RenumberTerminalsTask::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event)
    return true;
}


void RenumberTerminalsTask::drawBackground(QPainter *painter, const QRectF &rect)
{
    Q_UNUSED(painter)
    Q_UNUSED(rect)
}

void RenumberTerminalsTask::drawForeground(QPainter *painter, const QRectF &rect)
{
    Q_UNUSED(rect)

    if (m_hitPath.isEmpty())
        return;
//    painter->setBrush(Qt::NoBrush);
//    painter->setPen(QPen(scene()->graphicsPalette().color(LeGraphicsPalette::Highlight), 0));
//    painter->drawLine(m_hitPath.last());
}


bool RenumberTerminalsTask::keyPressEvent(QKeyEvent *event)
{
    Q_UNUSED(event)

    return false;
}

bool RenumberTerminalsTask::keyReleaseEvent(QKeyEvent *event)
{
    Q_UNUSED(event)

    return false;
}



void RenumberTerminalsTask::detachPropertyManager()
{
//    m_propertyManager->disconnect(this);
//    m_propertyManager->clear();
//    propertyBrowser()->unsetFactoryForManager(m_propertyManager);
}

void RenumberTerminalsTask::revertNumbering()
{
    for (int i=0; i<m_terminals.count(); i++)
    {
        m_terminals.at(i)->setLabel(m_originalNumbers.at(i));
        m_terminals.at(i)->setStateFlag(LeGraphicsStyle::MarkedBad, false);
        m_terminals.at(i)->setStateFlag(LeGraphicsStyle::MarkedGood, false);
    }
}

void RenumberTerminalsTask::applyNumbering()
{

}

void RenumberTerminalsTask::detachScene()
{
    //scene()->setEventFilter(nullptr);
}


QList<QGraphicsItem *> RenumberTerminalsTask::recursiveChildItems(QGraphicsItem *parentItem) const
{
    QList<QGraphicsItem *> result;
    for (QGraphicsItem *item: parentItem->childItems())
    {
        result.append(item);
        result.append(recursiveChildItems(item));
    }
    return result;
}


void RenumberTerminalsTask::initialiseNumbering()
{
//    m_terminals.clear();
//    m_originalNumbers.clear();
//    m_renumbered.clear();
//    m_candidates.clear();
//    m_hitPath.clear();
//    LeGraphicsItemLayer *layer = scene()->featureLayerByName("mcad");
//    for (QGraphicsItem *item: recursiveChildItems(layer))
//    {
//        if (item->type() == TerminalItem::Type)
//        {
//            auto term = static_cast<TerminalItem*>(item);
//            term->setStateFlag(LeGraphicsStyle::MarkedGood, false);
//            term->setStateFlag(LeGraphicsStyle::MarkedBad, true);
//            m_terminals.append(term);
//            m_originalNumbers.append(term->label());
//        }
//    }
//    m_toRenumber = m_terminals;
}

void RenumberTerminalsTask::attachPropertyManager()
{
    //propertyBrowser()->setFactoryForManager(m_propertyManager, m_propertyEditorFactory);
    //    auto prop = m_propertyManager->addProperty(QMetaType::QSizeF, "Size");
    //    prop->setValue(QSizeF(42, 666));
    //    propertyBrowser()->addProperty(prop);
}

void RenumberTerminalsTask::attachScene()
{
    //scene()->setEventFilter(this);
}
